//
//  BLEManager.m
//  BLESDK
//
//  Created on Desktop.
//

#import "BLEManager.h"
#import "BLESDK.h" // 引入BLESDK头文件，用于错误域

@interface BLEManager () <CBCentralManagerDelegate, CBPeripheralDelegate>

@property (nonatomic, strong) CBCentralManager *centralManager;
@property (nonatomic, strong, readwrite) CBPeripheral *connectedPeripheral;
@property (nonatomic, assign, readwrite) BOOL isBluetoothEnabled;
@property (nonatomic, assign, readwrite) BLEConnectionState connectionState;
@property (nonatomic, assign, readwrite) BOOL isScanning;

// 扫描和连接相关属性
@property (nonatomic, strong) NSTimer *scanTimer;
@property (nonatomic, strong) NSTimer *connectionTimer;
@property (nonatomic, strong) NSMutableDictionary<NSString *, CBPeripheral *> *discoveredPeripheralsDict;
@property (nonatomic, strong) NSString *connectingPeripheralUUID;
@property (nonatomic, assign) NSInteger reconnectCount;
@property (nonatomic, copy) void(^connectionCompletion)(BOOL success, NSError * _Nullable error);

// 扫描过滤属性
@property (nonatomic, strong) NSString *scanNamePrefix;
@property (nonatomic, assign) NSInteger scanRSSIThreshold;
@property (nonatomic, assign) BLEScanFilter scanFilter;

@end

@implementation BLEManager

#pragma mark - Life Cycle

+ (instancetype)sharedInstance {
    static BLEManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });
    return instance;
}

- (instancetype)init {
    self = [super init];
    if (self) {
        // 初始化属性
        _connectionState = BLEConnectionStateDisconnected;
        _isScanning = NO;
        _autoReconnectCount = 0;
        _scanDuration = 10.0;
        _connectionTimeout = 5.0;
        _scanRSSIThreshold = -70;
        _discoveredPeripheralsDict = [NSMutableDictionary dictionary];
        
        // 初始化中心管理器，设置代理和队列
        dispatch_queue_t queue = dispatch_get_main_queue();
        _centralManager = [[CBCentralManager alloc] initWithDelegate:self 
                                                               queue:queue
                                                             options:@{CBCentralManagerOptionShowPowerAlertKey: @YES}];
    }
    return self;
}

#pragma mark - SDK Options

- (void)applyOptions:(NSDictionary *)options {
    if (options[@"scanDuration"]) {
        self.scanDuration = [options[@"scanDuration"] doubleValue];
    }
    
    if (options[@"autoReconnect"]) {
        self.autoReconnectCount = [options[@"autoReconnect"] boolValue] ? 3 : 0;
    }
    
    if (options[@"connectionTimeout"]) {
        self.connectionTimeout = [options[@"connectionTimeout"] doubleValue];
    }
}

#pragma mark - Public Methods

- (void)startScanWithServices:(NSArray<CBUUID *> *)serviceUUIDs {
    [self startScanWithServices:serviceUUIDs namePrefix:nil rssiThreshold:-100 filter:BLEScanFilterNone];
}

- (void)startScanWithServices:(NSArray<CBUUID *> *)serviceUUIDs 
                   namePrefix:(NSString *)namePrefix 
                rssiThreshold:(NSInteger)rssiThreshold 
                       filter:(BLEScanFilter)filter {
    // 检查蓝牙状态
    if (self.centralManager.state != CBManagerStatePoweredOn) {
        NSLog(@"蓝牙未开启，无法扫描设备");
        return;
    }
    
    // 如果已经在扫描，先停止
    if (self.isScanning) {
        [self stopScan];
    }
    
    // 清空已发现的设备列表
    [self.discoveredPeripheralsDict removeAllObjects];
    
    // 保存过滤条件
    self.scanNamePrefix = namePrefix;
    self.scanRSSIThreshold = rssiThreshold;
    self.scanFilter = filter;
    
    // 设置扫描超时定时器
    self.scanTimer = [NSTimer scheduledTimerWithTimeInterval:self.scanDuration
                                                      target:self
                                                    selector:@selector(scanTimeout:)
                                                    userInfo:nil
                                                     repeats:NO];
    
    // 开始扫描设备
    self.isScanning = YES;
    [self.centralManager scanForPeripheralsWithServices:serviceUUIDs options:nil];
    NSLog(@"开始扫描蓝牙设备...");
}

- (void)stopScan {
    if (self.scanTimer) {
        [self.scanTimer invalidate];
        self.scanTimer = nil;
    }
    
    [self.centralManager stopScan];
    self.isScanning = NO;
    NSLog(@"停止扫描蓝牙设备");
}

- (void)connectPeripheral:(CBPeripheral *)peripheral {
    [self connectPeripheral:peripheral timeout:self.connectionTimeout completion:nil];
}

- (void)connectPeripheral:(CBPeripheral *)peripheral 
                  timeout:(NSTimeInterval)timeout 
               completion:(void(^)(BOOL success, NSError * _Nullable error))completion {
    if (!peripheral) {
        NSError *error = [NSError errorWithDomain:BLESDKErrorDomain 
                                             code:BLESDKErrorCodeInvalidParameter 
                                         userInfo:@{NSLocalizedDescriptionKey: @"设备为空"}];
        if (completion) {
            completion(NO, error);
        }
        return;
    }
    
    // 如果已经连接，直接返回成功
    if (self.connectionState == BLEConnectionStateConnected && self.connectedPeripheral == peripheral) {
        if (completion) {
            completion(YES, nil);
        }
        return;
    }
    
    // 如果正在连接其他设备，先取消
    if (self.connectionState == BLEConnectionStateConnecting) {
        [self disconnect];
    }
    
    // 保存连接中的设备UUID和回调
    self.connectingPeripheralUUID = peripheral.identifier.UUIDString;
    self.connectionCompletion = completion;
    self.reconnectCount = 0;
    
    // 更新连接状态
    self.connectionState = BLEConnectionStateConnecting;
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didUpdateConnectionState:forPeripheral:)]) {
        [self.delegate bleManager:self didUpdateConnectionState:self.connectionState forPeripheral:peripheral];
    }
    
    // 设置连接超时
    self.connectionTimer = [NSTimer scheduledTimerWithTimeInterval:timeout 
                                                           target:self 
                                                         selector:@selector(connectionTimeout:) 
                                                         userInfo:nil 
                                                          repeats:NO];
    
    // 开始连接
    [self.centralManager connectPeripheral:peripheral options:nil];
    NSLog(@"正在连接设备: %@", peripheral.name ?: @"未知设备");
}

- (void)disconnect {
    // 取消连接超时定时器
    if (self.connectionTimer) {
        [self.connectionTimer invalidate];
        self.connectionTimer = nil;
    }
    
    // 如果已连接或正在连接，断开连接
    if ((self.connectionState == BLEConnectionStateConnected || self.connectionState == BLEConnectionStateConnecting) && 
        self.connectedPeripheral != nil) {
        self.connectionState = BLEConnectionStateDisconnecting;
        
        // 通知代理
        if ([self.delegate respondsToSelector:@selector(bleManager:didUpdateConnectionState:forPeripheral:)]) {
            [self.delegate bleManager:self didUpdateConnectionState:self.connectionState forPeripheral:self.connectedPeripheral];
        }
        
        [self.centralManager cancelPeripheralConnection:self.connectedPeripheral];
    } else {
        // 没有连接的设备，或设备已为nil，直接更新状态
        self.connectionState = BLEConnectionStateDisconnected;
        NSLog(@"断开连接：无已连接的设备或设备已失效");
    }
}

- (BOOL)writeData:(NSData *)data forCharacteristic:(CBCharacteristic *)characteristic {
    if (!self.connectedPeripheral || !characteristic || !data) {
        NSLog(@"写入数据失败：参数无效");
        return NO;
    }
    
    // 检查连接状态
    if (self.connectionState != BLEConnectionStateConnected) {
        NSLog(@"写入数据失败：设备未连接");
        return NO;
    }
    
    CBCharacteristicProperties properties = characteristic.properties;
    
    if (properties & CBCharacteristicPropertyWriteWithoutResponse) {
        [self.connectedPeripheral writeValue:data 
                          forCharacteristic:characteristic 
                                       type:CBCharacteristicWriteWithoutResponse];
        return YES;
    } else if (properties & CBCharacteristicPropertyWrite) {
        [self.connectedPeripheral writeValue:data 
                          forCharacteristic:characteristic 
                                       type:CBCharacteristicWriteWithResponse];
        return YES;
    } else {
        NSLog(@"特征值不支持写入操作");
        return NO;
    }
}

- (void)readValueForCharacteristic:(CBCharacteristic *)characteristic {
    if (!self.connectedPeripheral || !characteristic) {
        NSLog(@"读取数据失败：参数无效");
        return;
    }
    
    // 检查连接状态
    if (self.connectionState != BLEConnectionStateConnected) {
        NSLog(@"读取数据失败：设备未连接");
        return;
    }
    
    if (characteristic.properties & CBCharacteristicPropertyRead) {
        [self.connectedPeripheral readValueForCharacteristic:characteristic];
    } else {
        NSLog(@"特征值不支持读取操作");
    }
}

- (void)setNotifyValue:(BOOL)enabled forCharacteristic:(CBCharacteristic *)characteristic {
    if (!self.connectedPeripheral || !characteristic) {
        NSLog(@"设置通知失败：参数无效");
        return;
    }
    
    // 检查连接状态
    if (self.connectionState != BLEConnectionStateConnected) {
        NSLog(@"设置通知失败：设备未连接");
        return;
    }
    
    if (characteristic.properties & CBCharacteristicPropertyNotify ||
        characteristic.properties & CBCharacteristicPropertyIndicate) {
        [self.connectedPeripheral setNotifyValue:enabled forCharacteristic:characteristic];
    } else {
        NSLog(@"特征值不支持通知操作");
    }
}

- (NSArray<CBPeripheral *> *)discoveredPeripherals {
    return [self.discoveredPeripheralsDict allValues];
}

- (nullable CBPeripheral *)peripheralWithName:(NSString *)name {
    if (!name) {
        return nil;
    }
    
    for (CBPeripheral *peripheral in [self.discoveredPeripheralsDict allValues]) {
        if ([peripheral.name isEqualToString:name]) {
            return peripheral;
        }
    }
    
    return nil;
}

- (nullable CBPeripheral *)peripheralWithUUIDString:(NSString *)UUIDString {
    return self.discoveredPeripheralsDict[UUIDString];
}

#pragma mark - Private Methods

- (void)scanTimeout:(NSTimer *)timer {
    [self stopScan];
}

- (void)connectionTimeout:(NSTimer *)timer {
    self.connectionTimer = nil;
    
    // 取消当前连接
    [self.centralManager cancelPeripheralConnection:self.connectedPeripheral];
    
    // 创建错误对象
    NSError *error = [NSError errorWithDomain:BLESDKErrorDomain 
                                         code:BLESDKErrorCodeOperationTimeout 
                                     userInfo:@{NSLocalizedDescriptionKey: @"连接超时"}];
    
    // 回调处理
    if (self.connectionCompletion) {
        self.connectionCompletion(NO, error);
        self.connectionCompletion = nil;
    }
    
    // 更新状态
    self.connectionState = BLEConnectionStateDisconnected;
    
    // 通知代理
    if (self.connectedPeripheral && [self.delegate respondsToSelector:@selector(bleManager:didUpdateConnectionState:forPeripheral:)]) {
        [self.delegate bleManager:self didUpdateConnectionState:self.connectionState forPeripheral:self.connectedPeripheral];
    }
    
    // 尝试自动重连
    [self tryAutoReconnect];
}

- (void)tryAutoReconnect {
    // 检查是否需要自动重连
    if (self.autoReconnectCount > 0 && self.reconnectCount < self.autoReconnectCount && self.connectingPeripheralUUID) {
        self.reconnectCount++;
        
        // 查找设备
        CBPeripheral *peripheral = [self peripheralWithUUIDString:self.connectingPeripheralUUID];
        if (peripheral) {
            NSLog(@"自动重连尝试 %ld/%ld...", (long)self.reconnectCount, (long)self.autoReconnectCount);
            
            // 延迟一秒重连
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self connectPeripheral:peripheral];
            });
        }
    }
}

- (BOOL)shouldFilterPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
    // 如果没有过滤条件，则不过滤
    if (self.scanFilter == BLEScanFilterNone) {
        return NO;
    }
    
    // 根据名称过滤
    if ((self.scanFilter & BLEScanFilterName) && self.scanNamePrefix) {
        NSString *name = peripheral.name;
        if (!name || ![name hasPrefix:self.scanNamePrefix]) {
            return YES; // 不符合名称条件，应该过滤
        }
    }
    
    // 根据RSSI过滤
    if ((self.scanFilter & BLEScanFilterRSSI) && RSSI) {
        if ([RSSI integerValue] < self.scanRSSIThreshold) {
            return YES; // 信号强度不够，应该过滤
        }
    }
    
    // 根据服务过滤
    if ((self.scanFilter & BLEScanFilterServices)) {
        NSArray *serviceUUIDs = advertisementData[CBAdvertisementDataServiceUUIDsKey];
        if (!serviceUUIDs || [serviceUUIDs count] == 0) {
            return YES; // 没有广播服务，应该过滤
        }
    }
    
    return NO; // 通过所有过滤条件
}

#pragma mark - CBCentralManagerDelegate

- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    switch (central.state) {
        case CBManagerStatePoweredOn:
            NSLog(@"蓝牙已开启");
            self.isBluetoothEnabled = YES;
            break;
        case CBManagerStatePoweredOff:
            NSLog(@"蓝牙已关闭");
            self.isBluetoothEnabled = NO;
            
            // 蓝牙关闭时，停止扫描并断开连接
            [self stopScan];
            [self disconnect];
            break;
        case CBManagerStateResetting:
            NSLog(@"蓝牙正在重置");
            self.isBluetoothEnabled = NO;
            break;
        case CBManagerStateUnauthorized:
            NSLog(@"蓝牙未授权");
            self.isBluetoothEnabled = NO;
            break;
        case CBManagerStateUnsupported:
            NSLog(@"设备不支持蓝牙");
            self.isBluetoothEnabled = NO;
            break;
        case CBManagerStateUnknown:
            NSLog(@"蓝牙状态未知");
            self.isBluetoothEnabled = NO;
            break;
        default:
            break;
    }
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didUpdateState:)]) {
        [self.delegate bleManager:self didUpdateState:central.state];
    }
}

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI {
    // 过滤设备
    if ([self shouldFilterPeripheral:peripheral advertisementData:advertisementData RSSI:RSSI]) {
        return;
    }
    
    // 保存到已发现设备字典
    if (peripheral.identifier) {
        self.discoveredPeripheralsDict[peripheral.identifier.UUIDString] = peripheral;
    }
    
    NSLog(@"发现设备: %@, RSSI: %@", peripheral.name ?: @"未知设备", RSSI);
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didDiscoverPeripheral:advertisementData:RSSI:)]) {
        [self.delegate bleManager:self didDiscoverPeripheral:peripheral advertisementData:advertisementData RSSI:RSSI];
    }
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    // 取消连接超时定时器
    if (self.connectionTimer) {
        [self.connectionTimer invalidate];
        self.connectionTimer = nil;
    }
    
    NSLog(@"已连接设备: %@", peripheral.name ?: @"未知设备");
    self.connectedPeripheral = peripheral;
    peripheral.delegate = self;
    
    // 更新连接状态
    self.connectionState = BLEConnectionStateConnected;
    self.reconnectCount = 0;
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didUpdateConnectionState:forPeripheral:)]) {
        [self.delegate bleManager:self didUpdateConnectionState:self.connectionState forPeripheral:peripheral];
    }
    
    if ([self.delegate respondsToSelector:@selector(bleManager:didConnectPeripheral:)]) {
        [self.delegate bleManager:self didConnectPeripheral:peripheral];
    }
    
    // 连接成功回调
    if (self.connectionCompletion) {
        self.connectionCompletion(YES, nil);
        self.connectionCompletion = nil;
    }
    
    // 连接成功后开始搜索服务
    [peripheral discoverServices:nil];
}

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    // 取消连接超时定时器
    if (self.connectionTimer) {
        [self.connectionTimer invalidate];
        self.connectionTimer = nil;
    }
    
    NSLog(@"连接设备失败: %@, 错误: %@", peripheral.name ?: @"未知设备", error.localizedDescription);
    
    // 创建错误对象
    NSError *sdkError = [NSError errorWithDomain:BLESDKErrorDomain 
                                            code:BLESDKErrorCodeConnectionFailed 
                                        userInfo:@{NSLocalizedDescriptionKey: @"连接设备失败", 
                                                   NSUnderlyingErrorKey: error ?: [NSNull null]}];
    
    // 更新状态
    self.connectionState = BLEConnectionStateDisconnected;
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didUpdateConnectionState:forPeripheral:)]) {
        [self.delegate bleManager:self didUpdateConnectionState:self.connectionState forPeripheral:peripheral];
    }
    
    if ([self.delegate respondsToSelector:@selector(bleManager:didFailToConnectPeripheral:error:)]) {
        [self.delegate bleManager:self didFailToConnectPeripheral:peripheral error:error];
    }
    
    // 连接失败回调
    if (self.connectionCompletion) {
        self.connectionCompletion(NO, sdkError);
        self.connectionCompletion = nil;
    }
    
    // 尝试自动重连
    [self tryAutoReconnect];
}

- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@"断开连接: %@, 错误: %@", peripheral.name ?: @"未知设备", error ? error.localizedDescription : @"无");
    
    // 更新状态
    BOOL wasConnected = (self.connectedPeripheral == peripheral);
    self.connectionState = BLEConnectionStateDisconnected;
    
    if (wasConnected) {
        self.connectedPeripheral = nil;
    }
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didUpdateConnectionState:forPeripheral:)]) {
        [self.delegate bleManager:self didUpdateConnectionState:self.connectionState forPeripheral:peripheral];
    }
    
    if ([self.delegate respondsToSelector:@selector(bleManager:didDisconnectPeripheral:error:)]) {
        [self.delegate bleManager:self didDisconnectPeripheral:peripheral error:error];
    }
    
    // 如果是异常断开连接且有错误，尝试自动重连
    if (error && wasConnected) {
        [self tryAutoReconnect];
    }
}

#pragma mark - CBPeripheralDelegate

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    if (error) {
        NSLog(@"发现服务错误: %@", error.localizedDescription);
        return;
    }
    
    NSLog(@"发现服务数量: %ld", (long)peripheral.services.count);
    
    // 遍历所有服务，搜索特征值
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:nil forService:service];
    }
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didDiscoverServices:forPeripheral:)]) {
        [self.delegate bleManager:self didDiscoverServices:peripheral.services forPeripheral:peripheral];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {
        NSLog(@"发现特征值错误: %@", error.localizedDescription);
        return;
    }
    
    NSLog(@"服务 %@ 发现特征值数量: %ld", service.UUID, (long)service.characteristics.count);
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didDiscoverCharacteristics:forService:peripheral:)]) {
        [self.delegate bleManager:self didDiscoverCharacteristics:service.characteristics forService:service peripheral:peripheral];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"读取特征值数据错误: %@", error.localizedDescription);
        return;
    }
    
    NSLog(@"收到特征值数据: %@, 长度: %ld", characteristic.UUID, (long)characteristic.value.length);
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didUpdateValueForCharacteristic:peripheral:)]) {
        [self.delegate bleManager:self didUpdateValueForCharacteristic:characteristic peripheral:peripheral];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"写入特征值数据错误: %@", error.localizedDescription);
    } else {
        NSLog(@"写入特征值数据成功");
    }
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didWriteValueForCharacteristic:error:)]) {
        [self.delegate bleManager:self didWriteValueForCharacteristic:characteristic error:error];
    }
}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"设置通知状态错误: %@", error.localizedDescription);
    } else {
        NSLog(@"设置通知状态成功: %@, 已开启: %d", characteristic.UUID, characteristic.isNotifying);
    }
    
    // 通知代理
    if ([self.delegate respondsToSelector:@selector(bleManager:didUpdateNotificationStateForCharacteristic:enabled:error:)]) {
        [self.delegate bleManager:self didUpdateNotificationStateForCharacteristic:characteristic enabled:characteristic.isNotifying error:error];
    }
}

@end 
